package processing.test.mechaapp;

import processing.core.*;

import java.util.Random;
import java.util.ArrayList;
import java.util.Iterator;

import android.content.Context;
import android.os.Looper;
import android.os.Vibrator;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;

public class MechaApp extends PApplet {
	// 2D Array of objects
	Atom grid[][];

	int CurScore;
	int HiScore;
	int CurBonus;
	int deductions;

	String[] scores;
	int i;

	final int STATE_WELCOME = 0;
	final int STATE_TIMED = 1;
	final int STATE_STRATEGY = 2;
	final int STATE_INSTRUCTIONS = 3;
	final int STATE_HIGHSCORE = 4;
	final int STATE_PAUSED = 5;
	final int STATE_GAMEOVER = 6;

	PImage background;
	PImage timedButton;
	PImage strategyButton;
	PImage instructButton;
	PImage highscoreButton;
	PImage gameBackground;
	PImage mainmenuButton;
	PImage pauseButton;
	PImage pauseBackground;
	PImage gameoverBackground;
	PImage hiscoresButton;
	PImage hydrogen; //1
	PImage oxygen;//2
	PImage nitrogen;//3
	PImage carbon; //4

	// State of the program; Initialized at 0
	int state = STATE_WELCOME;
	int prevState;
	
	// Timer used for timing game modes
	//TimerClass timer;
	AppTimer timer;

	// Number of columns and rows in the grid
	private final int cols = 8;
	private int rows = 8;

	int Ox, Ca, Ni, Hy, Bk;

	float sz;
	Random rand = new Random();
	Atom selectedAtom = null;

	// these vars are for spawning new atoms with respect to the number of moves
	// a player makes
	int spawnAtom;
	int numOfMoves;
	int numAtoms = 0;
	int oldNumAtoms = 0;

	private ArrayList<Molecule> history;

	// android gestures
	GestureDetector listener;
	GestureListener context;

	// for vibrate to work you must add this to the AndroidManifest under the
	// manifest tag:
	// <uses-permission android:name="android.permission.VIBRATE"/>
	// ANDROID vibrate
	Vibrator vibrate;

	public void setup() {
		orientation(PORTRAIT);
		smooth();
		Atom.setApplet(this); // This statement needs to be called in order to
								// use proccessing's API!
		//TimerClass.setApplet(this);
		sz = (width / cols);
		Atom.size = (float) (sz / (1.4));
		
		//timer = new TimerClass(120000, width / 2, 575);
		timer = new AppTimer(this, "ifGameOver", width/2, 575);

		// android gestures
		Looper.prepare();
		context = new GestureListener(this);
		context.setSingleTap("singleTap");
		context.setSwipe("swipe");
		context.setDoubleTap("doubleTap");
		listener = new GestureDetector(context);

		// ANDROID vibrate
		vibrate = (Vibrator) this.getSystemService(Context.VIBRATOR_SERVICE);

		// Load Images
		background = loadImage("welcome_bg.bmp");
		timedButton = loadImage("timed_button.png");
		strategyButton = loadImage("strategy_button.png");
		instructButton = loadImage("instructions_button.png");
		highscoreButton = loadImage("highscores_button.png");
		gameBackground = loadImage("gameMode_bg.bmp");
		mainmenuButton = loadImage("mainmenu_button.bmp");
		pauseButton = loadImage("pause_button.bmp");
		pauseBackground = loadImage("pause_bg.bmp");
		gameoverBackground = loadImage("gameover_bg.bmp");
		hiscoresButton = loadImage("hiscores_button.bmp");
		hydrogen=loadImage("mol1.png"); //1
		oxygen=loadImage("mol2.png");//2
		nitrogen=loadImage("mol3.png");//3
		carbon=loadImage("mol4.png"); //4
		
		//Load of High Scores, and udpate class variable
		scores = loadStrings("SCORES");
		System.out.println("Hi Score is ");
		for (i = 0; i < scores.length; i++) {
			System.out.println(scores[i]);
		}
		String s1 = scores[0];
		HiScore = Integer.parseInt(s1);
		
		// Resizes Background Images
		background.resize(width, height);
		gameBackground.resize(width, height);
		pauseBackground.resize(width, height);
		gameoverBackground.resize(width, height);
		
		noLoop();

		Log.i("SETUP", "Setup is completed");
	}

	public void draw() {
		// Welcome Screen
		if (state == STATE_WELCOME) {
			background(background);
			image(timedButton, 15, 17);
			image(strategyButton, 243, 128);
			image(instructButton, 15, 437);
			image(highscoreButton, 243, 554);
		}
		// Timed Mode
		else if (state == STATE_TIMED) {
			background(gameBackground);
			image(mainmenuButton, 260, 706);
			image(pauseButton, 20, 706);
			//timer.display();
			if(grid != null){
				for (int i = 0; i < cols; i++) {
					for (int j = 0; j < rows; j++) {
						grid[i][j].drawLines();
					}
				}
				for (int i = 0; i < cols; i++) {
					for (int j = 0; j < rows; j++) {
						grid[i][j].drawMe();
					}
				}
			}
			refreshScores();
		}
		// Strategy Mode
		else if (state == STATE_STRATEGY) {
			background(gameBackground);
			image(mainmenuButton, 260, 706);
			image(pauseButton, 20, 706);
			if(grid != null){
				for (int i = 0; i < cols; i++) {
					for (int j = 0; j < rows; j++) {
						grid[i][j].drawLines();
					}
				}
				for (int i = 0; i < cols; i++) {
					for (int j = 0; j < rows; j++) {
						grid[i][j].drawMe();
					}
				}
			}
			refreshScores();
		}
		// Instructions Screen
		else if (state == STATE_INSTRUCTIONS) {
			background(0);
			// TO DO
		}
		// High Score Screen
		else if (state == STATE_HIGHSCORE) {
			background(0);
			// TO DO
		}
		// Pause Screen
		else if (state == STATE_PAUSED) {
			background(pauseBackground);
		}
		else if (state == STATE_GAMEOVER) {
			background(gameoverBackground);
			image(mainmenuButton, 260, 463);
			image(hiscoresButton, 20, 463);

			PFont font;
			font = loadFont("Roboto-Bold-48.vlw");
			fill(255);
			textFont(font);
			textAlign(PConstants.CENTER);
			text(CurScore, width / 2, 439);
		}
	}

	// fired when the screen is first touch, which in turns fires onTouchEvent
	// ------not continuous-----
	// ANDROID
	public boolean surfaceTouchEvent(MotionEvent event) {
		mouseX = (int) event.getX();
		mouseY = (int) event.getY();
		
		// Welcome Screen mouseClicked Event
		if (state == STATE_WELCOME) {
			// Timed Mode Button
			if (atomOver(30 + (199 / 2), 30 + (199 / 2), 199)) {
				state = STATE_TIMED;
				
				history = new ArrayList<Molecule>();
				spawnAtom = 12;
				numOfMoves = CurScore = CurBonus = deductions = numAtoms = 0;
				grid = new Atom[cols][rows];
				Ox = 45; Ca = 15; Ni = 30; Hy = 70; Bk = 150;
				for (int i = 0; i < cols; i++) {
					for (int j = 0; j < rows; j++) {
						spawnNewAtom(i, j, Spawn(Bk, Hy, Ox, Ni, Ca));
					}
				}
				Ox = 45; Ca = 15; Ni = 30; Hy = 180;
				
				//timer.setDirection(TimerClass.COUNTDOWN);
				timer.setDirection(AppTimer.COUNT_DOWN);
				timer.start(120);
			}
			// Strategy Mode Button
			if (atomOver(257 + (199 / 2), 141 + (199 / 2), 199)) {
				state = STATE_STRATEGY;
				
				history = new ArrayList<Molecule>();
				spawnAtom = 10;
				numOfMoves = CurScore = CurBonus = deductions = numAtoms = oldNumAtoms = 0;
				grid = new Atom[cols][rows];
				Ox = 40; Ca = 15; Ni = 25; Hy = 65; Bk = 100;
				for (int i = 0; i < cols; i++) {
					for (int j = 0; j < rows; j++) {
						spawnNewAtom(i, j, Spawn(Bk, Hy, Ox, Ni, Ca));
					}
				}
				Ox = 30; Ca = 5; Ni = 10; Hy = 100;
				oldNumAtoms = numAtoms;
				
				//timer.setDirection(TimerClass.COUNTUP);
				timer.setDirection(AppTimer.COUNT_UP);
				timer.start(0);
			}
			// Instructions Button
			if (atomOver(30 + (199 / 2), 450 + (199 / 2), 199)) {
				state = STATE_INSTRUCTIONS;
			}
			// High Scores Button
			if (atomOver(257 + (199 / 2), 567 + (199 / 2), 199)) {
				state = STATE_HIGHSCORE;
			}
		}
		if (state == STATE_PAUSED) {
			// If player touches screen, game resumes
			timer.resume();
			state = prevState;
		}
		if (state == STATE_TIMED || state == STATE_STRATEGY) {
			// Pause Button
			if (overRect(20, 706, 200, 64)) {
				prevState = state;
				timer.pause();
				state = STATE_PAUSED;
			}
			// Main Menu Button
			if (overRect(260, 706, 200, 64)) {
				timer.stop();
				state = STATE_WELCOME;
				grid = null;
				history = null;
				
				System.gc();//for garbage collection
			}
		}
		if (state == STATE_GAMEOVER) {
			// Hi Scores Button
			if (overRect(20, 463, 200, 64)) {
				timer.stop();
				state = STATE_HIGHSCORE;
				
				System.gc();//for garbage collection
			}
			// Main Menu Button
			if (overRect(260, 463, 200, 64)) {
				timer.stop();
				state = STATE_WELCOME;
				
				System.gc();//for garbage collection
			}
		}
		redraw();
		return false;
	}

	// fired when the user is touching the screen
	// -------is continuous-------
	// ANDROID
	public boolean onTouchEvent(MotionEvent event) {
		boolean result;
		
		if (state == STATE_TIMED || state == STATE_STRATEGY) {
			result = listener.onTouchEvent(event);
		} else
			result = false;
		return result;
	}

	// sets the selectedAtom to the atom the user clicked on
	// it DOES NOT set or break bonds
	// ANDROID
	public void singleTap() {
		Atom temp = null;
		boolean found = false;

		for (int i = 0; i < cols && !found; i++) {
			for (int j = 0; j < rows && !found; j++) {
				temp = grid[i][j];

				if (!(temp instanceof blankAtom)
						&& atomOver(temp.xChord, temp.yChord, temp.size)) {
					found = true;
				}

			}
		}

		if (found && selectedAtom != null && selectedAtom != temp) {
			selectedAtom.highlight = false;
			selectedAtom = temp;
			selectedAtom.highlight = true;

		} else if (found && selectedAtom == null) {
			selectedAtom = temp;
			selectedAtom.highlight = true;
		} else if (selectedAtom != null) {
			selectedAtom.highlight = false;
			selectedAtom = null;
		}
		redraw();
	}

	// ANDROID
	public void swipe(int direction) {
		if (selectedAtom == null)
			return;
		Atom temp = null;

		switch (direction) {
		case GestureListener.SWIPE_UP:
			if (selectedAtom.jth > 0)
				temp = grid[selectedAtom.ith][selectedAtom.jth - 1];
			break;
		case GestureListener.SWIPE_DOWN:
			if (selectedAtom.jth < rows - 1)
				temp = grid[selectedAtom.ith][selectedAtom.jth + 1];
			break;
		case GestureListener.SWIPE_LEFT:
			if (selectedAtom.ith > 0)
				temp = grid[selectedAtom.ith - 1][selectedAtom.jth];
			break;
		case GestureListener.SWIPE_RIGHT:
			if (selectedAtom.ith < cols - 1)
				temp = grid[selectedAtom.ith + 1][selectedAtom.jth];
			break;

		default:
			Log.e("SWIPE", "Direction not recognized");
		}

		g.beginDraw();
		if (temp != null) {
			breakAtom(temp);
			breakAtom(selectedAtom);

			// switch in the grid
			grid[temp.ith][temp.jth] = grid[selectedAtom.ith][selectedAtom.jth];
			grid[selectedAtom.ith][selectedAtom.jth] = temp;

			// switch graphically here
			float tempX = selectedAtom.xChord;
			float tempY = selectedAtom.yChord;
			int tempI = selectedAtom.ith;
			int tempJ = selectedAtom.jth;

			selectedAtom.xChord = temp.xChord;
			selectedAtom.yChord = temp.yChord;
			selectedAtom.ith = temp.ith;
			selectedAtom.jth = temp.jth;

			temp.xChord = tempX;
			temp.yChord = tempY;
			temp.ith = tempI;
			temp.jth = tempJ;

			setAtom(temp);
			setAtom(selectedAtom);

			processMolecule(selectedAtom.molecule);
			if (!(temp instanceof blankAtom)
					&& selectedAtom.molecule != temp.molecule)
				processMolecule(temp.molecule);
		}
		atomSpawnChance();
		ifGameOver();
		draw();
		g.endDraw();
	}
	
	//does not move an atom, but a doubleTap will make bonds to all adjacent
	//atoms.
	//ANDROID
	public void doubleTap(){
		Atom temp = null;
		boolean found = false;
		
		g.beginDraw();
		for (int i = 0; i < cols && !found; i++) {
			for (int j = 0; j < rows && !found; j++) {
				temp = grid[i][j];

				if (!(temp instanceof blankAtom)
						&& atomOver(temp.xChord, temp.yChord, temp.size)) {
					found = true;
				}
			}
		}
		
		if(found){
			breakAtom(temp);
			setAtom(temp);
			processMolecule(temp.molecule);
			atomSpawnChance();
			
			ifGameOver();
		}
		draw();
		g.endDraw();
	}

	// the order of bonding goes as follows:
	// up, n.east, right, s.east, down, s.west, left, n.west
	private void setAtom(Atom atom) {
		if (atom instanceof blankAtom)
			return;

		if (atom.jth > 0)
			atom.makeBond(grid[atom.ith][atom.jth - 1]);// up
		if ((atom.ith < cols - 1) && (atom.jth > 0))
			atom.makeBond(grid[atom.ith + 1][atom.jth - 1]);// n.east
		if (atom.ith < cols - 1)
			atom.makeBond(grid[atom.ith + 1][atom.jth]); // right
		if ((atom.ith < cols - 1) && (atom.jth < rows - 1))
			atom.makeBond(grid[atom.ith + 1][atom.jth + 1]);// s.east
		if (atom.jth < rows - 1)
			atom.makeBond(grid[atom.ith][atom.jth + 1]);// down
		if ((atom.ith > 0) && (atom.jth < rows - 1))
			atom.makeBond(grid[atom.ith - 1][atom.jth + 1]);// s.west
		if (atom.ith > 0)
			atom.makeBond(grid[atom.ith - 1][atom.jth]);// left
		if ((atom.ith > 0) && (atom.jth > 0))
			atom.makeBond(grid[atom.ith - 1][atom.jth - 1]);// n.west
	}

	private void breakAtom(Atom atom) {
		if (atom instanceof blankAtom)
			return;

		if (atom.jth > 0)
			atom.breakBond(grid[atom.ith][atom.jth - 1]);// up
		if ((atom.ith < cols - 1) && (atom.jth > 0))
			atom.breakBond(grid[atom.ith + 1][atom.jth - 1]);// n.east
		if (atom.ith < cols - 1)
			atom.breakBond(grid[atom.ith + 1][atom.jth]); // right
		if ((atom.ith < cols - 1) && (atom.jth < rows - 1))
			atom.breakBond(grid[atom.ith + 1][atom.jth + 1]);// s.east
		if (atom.jth < rows - 1)
			atom.breakBond(grid[atom.ith][atom.jth + 1]);// down
		if ((atom.ith > 0) && (atom.jth < rows - 1))
			atom.breakBond(grid[atom.ith - 1][atom.jth + 1]);// s.west
		if (atom.ith > 0)
			atom.breakBond(grid[atom.ith - 1][atom.jth]);// left
		if ((atom.ith > 0) && (atom.jth > 0))
			atom.breakBond(grid[atom.ith - 1][atom.jth - 1]);// n.west
	}

	// this method determines if the mouse is over an atom
	// returns true if it is, and false otherwise- jt
	private boolean atomOver(float x, float y, float diameter) {
		float disX = x - this.mouseX;
		float disY = y - this.mouseY;
		if (sqrt(sq(disX) + sq(disY)) < diameter / 2) {
			return true;
		} else {
			return false;
		}

	}

	// returns a value 0-4 with certain probabilities
	private int Spawn(int B, int H, int O, int N, int C) {
		// changed the array size from 100 because the sum of all
		// the numbers in the parameter may not equal 100 - jt
		int[] Chance = new int[B + H + O + N + C];
		int i, result;
		int j = 0;

		for (i = 0; i < B; i++) {
			Chance[j] = 0;
			j++;
		}
		for (i = 0; i < H; i++) {
			Chance[j] = 1;
			j++;
		}
		for (i = 0; i < O; i++) {
			Chance[j] = 2;
			j++;
		}
		for (i = 0; i < N; i++) {
			Chance[j] = 3;
			j++;
		}
		for (i = 0; i < C; i++) {
			Chance[j] = 4;
			j++;
		}

		result = rand.nextInt(B + H + O + N + C);

		return Chance[result];

	}

	// creates a new atom in the grid at indices i and j
	// with the third parameter determining which atom will be created - jt
	private void spawnNewAtom(int i, int j, int determinate) {
		numAtoms++;
		switch (determinate) {
		case 1:
			grid[i][j] = new Hydrogen(i * sz + (sz / 2), j * sz + (sz / 2), i, j, hydrogen);
			break;
		case 2:
			grid[i][j] = new Oxygen(i * sz + (sz / 2), j * sz + (sz / 2), i, j, oxygen);
			break;
		case 3:
			grid[i][j] = new Nitrogen(i * sz + (sz / 2), j * sz + (sz / 2), i, j, nitrogen);
			break;
		case 4:
			grid[i][j] = new Carbon(i * sz + (sz / 2), j * sz + (sz / 2), i, j, carbon);
			break;

		default:
			grid[i][j] = new blankAtom(i * sz + (sz / 2), j * sz + (sz / 2), i,
					j);
			numAtoms--;
		}
	}

	// this method will be responsible for erasing molecules, adding molecules
	// to history
	// and give points based on the molecule created.
	//also adjusts difficulty
	private void processMolecule(Molecule molecule) {
		int score = 0;
		int bonus = 0;
		boolean newMolecule = true;

		if (molecule.checkCompleteness()) {
			g.beginDraw();
			score = molecule.eraseMolecule(grid, sz);//erases the molecule
			draw();
			g.endDraw();

			numAtoms -= molecule.count;
			System.out.println("Subtracting from count: "+molecule.count);

			// add molecule to the history list if it does not equal to any of
			// the molecules
			// in the history. that way we don't have "repeat" molecules in the
			// history
			Iterator<Molecule> itr = history.iterator();
			Molecule tempMolecule;
			while (itr.hasNext() && newMolecule) {
				tempMolecule = itr.next();
				if (molecule.compareTo(tempMolecule))
					newMolecule = false;
			}
			if(newMolecule){
				history.add(molecule);
				bonus = score/2;
			}
			
			vibrate.vibrate(500);// vibrate the phone
			Log.i("VIBRATOR", "phone vibrated for 500 milliseconds");
			
			//add to score and modify difficulty
			if(state == STATE_STRATEGY){
				if(newMolecule){
					if(molecule.count == 5)
						bonus = score/2;
					else if(molecule.count > 5)
						bonus = (int) (score * (molecule.count / 10.0));
					CurBonus += bonus;
					CurScore += score += bonus;
				}
				
				oldNumAtoms = numAtoms;
				
				if(CurScore <= 1000 && CurScore > 2000){
					spawnAtom = 8;
					Ox = 45; Hy = 120; Ca = 10; Ni = 25;
				}
				else if(CurScore <= 2000 && CurScore < 3500){
					spawnAtom = 6;
					Ox = 45; Hy = 80; Ca = 15; Ni = 30;
				}
				else if(CurScore <= 3500 && CurScore < 5500){
					spawnAtom = 5;
					Ox = 45; Hy = 50; Ca = 20; Ni = 30;
				}
				else if(CurScore <= 5500 && CurScore < 8000){
					spawnAtom = 4;
					Ox = 40; Hy = 40; Ca = 30; Ni = 40;
				}
				else if(CurScore <= 8000 && CurScore < 11000) {
					spawnAtom = 3;
					Ox = 35; Hy = 30; Ca = 30; Ni = 40;
				}
				else if(CurScore >= 15000){
					spawnAtom = 2;
					Ox = 30; Hy = 20; Ca = 40; Ni = 50;
				}
				
			}
			else if(state == STATE_TIMED){
				if(molecule.count == 5)
					bonus = score;
				else if(molecule.count > 5)
					bonus = (int) (score * (molecule.count / 5.0));
				if(newMolecule)
					bonus *= 2;
				CurBonus += bonus;
				CurScore += score += bonus;
				
				if(CurScore >= 20000){
					spawnAtom = 3;
					Ox = 20; Hy = 20; Ca = 20; Ni = 20;
				}
			}
			
			System.out.println("Bonus = " + bonus + "  Score is "
					+ CurScore);
			if (CurScore >= HiScore){
				HiScore = CurScore;
			}
		}
	}
	
	private boolean overRect(int x, int y, int width, int height) 
	{
	  if (mouseX >= x && mouseX <= x+width && 
	      mouseY >= y && mouseY <= y+height) {
	    return true;
	  } else {
	    return false;
	  }
	}
	
	public void ifGameOver(){
		System.out.println("numAtoms = "+numAtoms);
		
		boolean gameEnding = false;
		
		if(state == STATE_TIMED){
			if(numAtoms <= 0) gameEnding = true;
			else if(numAtoms == cols*rows) gameEnding = true;
			else if(numAtoms <= 4){
				int H=0, O=0, N=0, C=0;
				Atom temp;
				
				for (int i = 0; i < cols; i++) {
					for (int j = 0; j < rows; j++) {
						temp = grid[i][j];
						if(temp instanceof Oxygen)
							O++;
						else if(temp instanceof Hydrogen)
							H++;
						else if(temp instanceof Carbon)
							C++;
						else if(temp instanceof Nitrogen)
							N++;
					}
				}
				
				System.out.println("checking < 5");
				if(H<=2||O<=2||C!=3||(N!=2&&O!=1)||(N!=1&&H!=1&&0!=1)||
						(C!=2&&N!=1&&O!=1)){
					int tempNum = numOfMoves;
					for(int i=0; i<4; i++){
						numOfMoves = spawnAtom;
						atomSpawnChance();
					}
					numOfMoves = tempNum;
				}
			}
			else if(timer.getTime() <= 0)gameEnding = true;
		}
		else if(state == STATE_STRATEGY){
			if(numAtoms <= 0) gameEnding = true;
			else if(numAtoms - oldNumAtoms == 5) gameEnding = true;//if 5 new atoms are created before a new molecule is made.
			else if(numAtoms <= 4){
				int H=0, O=0, N=0, C=0;
				Atom temp;
				
				for (int i = 0; i < cols; i++) {
					for (int j = 0; j < rows; j++) {
						temp = grid[i][j];
						if(temp instanceof Oxygen)
							O++;
						else if(temp instanceof Hydrogen)
							H++;
						else if(temp instanceof Carbon)
							C++;
						else if(temp instanceof Nitrogen)
							N++;
					}
				}
				
				System.out.println("checking < 5");
				if(H<=2||O<=2||C!=3||(N!=2&&O!=1)||(N!=1&&H!=1&&0!=1)||
						(C!=2&&N!=1&&O!=1))
					gameEnding = true;
			}
		}
		
		if(gameEnding && numAtoms != 0){
			Atom temp;
			for (int i = 0; i < cols; i++) {
				for (int j = 0; j < rows; j++) {
					temp = grid[i][j];
					if(!(temp instanceof blankAtom))
						deductions += temp.points;
				}
			}
		}
		
		if(gameEnding){
			grid = null;
			history = null;
			System.gc();//garbage collection flag.
			state = STATE_GAMEOVER;
			System.out.println("--------------GAMEOVER--------------");
			System.out.println("Score: "+(CurScore-CurBonus)+"\nBonus: "+CurBonus+
					"\nDeductions: "+deductions);
			CurScore -= deductions;
			if (CurScore >= HiScore){
				HiScore = CurScore;
				SaveScores(HiScore, scores);
			}
		}
	}
	
	private String[] SaveScores(int HiScore, String[] scores) {
		String s1;
		String s2;
		int max = scores.length-1;
		if (scores.length > 0) {
			
			s1 = scores[max];
			s2 = scores[0];
			//HiScore does not break the list of top scores
			if(HiScore < parseInt(s1)){
				saveStrings("SCORES", scores);
				return scores;
			}
			
			//HiScore is the players highest score yet
			if(HiScore > parseInt(s2)){
				for (i = 0; i < (scores.length - 1); i++) {
					scores[i + 1] = scores[i];
				}
					scores[0] = Integer.toString(HiScore);
					saveStrings("SCORES", scores);

					return scores;
			}
				
			//If HiScore is a top score but not THE top score 
			//then search through to find index of first score greater than HiScore
			while(HiScore > parseInt(s1) && max >= 0 ) {
				max--;
				s1 = scores[max];
			}
			
			for (i = max+1; i < (scores.length - 1); i++) {
				scores[i + 1] = scores[i];
			}
			scores[max+1] = Integer.toString(HiScore);
			
			saveStrings("SCORES", scores);
		}
		return scores;

	}
	
	private void atomSpawnChance(){
		numOfMoves++;
		if (numOfMoves >= spawnAtom) {
			// don't create a new atom if the board is already full
			if (numAtoms < cols*rows) {
				int ith = rand.nextInt(8);
				int jth = rand.nextInt(8);
				while (!(grid[ith][jth] instanceof blankAtom)) {
					ith = rand.nextInt(8);
					jth = rand.nextInt(8);
				}

				spawnNewAtom(ith, jth, Spawn(0, Hy, Ox, Ni, Ca));
			}
			numOfMoves = 0;
		}
	}
	
	private void refreshScores() {
		PFont font;
		font = loadFont("Roboto-Bold-48.vlw");
		fill(255);
		textFont(font);
		textAlign(PConstants.LEFT);
		textSize(22);
		text(CurScore, 198, 629);
		text(HiScore, 198, 678);
	}
	
	public void redraw(){
		
		/*g.beginDraw();//using this, its draws every time, but its slow
		this.draw();
		g.endDraw();*/
		super.redraw();//using this, it only seems to redraw only sometimes
		super.redraw();
	}

}